import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import os


def check_data_shape(df):
    """检查数据形状"""
    print("数据形状检查:")
    print(f"行数: {df.shape[0]}, 列数: {df.shape[1]}")
    return df.shape


def check_duplicates(df):
    """检查重复值"""
    print("\n重复值检查:")
    duplicate_cols = ['代码', '名称', '详细']
    for col in duplicate_cols:
        if col in df.columns:
            duplicates = df[col].duplicated().sum()
            print(f"变量 '{col}' 的重复值数量: {duplicates}")
        else:
            print(f"警告: 列 '{col}' 不存在")


def display_first_rows(df, n=5):
    """展示前n行数据"""
    print(f"\n前{n}行数据:")
    print(df.head(n))
    return df.head(n)


def process_listing_date(df):
    """处理上市日期，提取年、月、日变量"""
    if '上市日期' not in df.columns:
        print("警告: '上市日期' 列不存在")
        return df

    print("\n处理上市日期...")

    # 尝试不同的日期格式
    date_formats = ['%Y-%m-%d', '%Y/%m/%d', '%Y年%m月%d日', '%Y.%m.%d']

    for fmt in date_formats:
        try:
            df['上市日期'] = pd.to_datetime(df['上市日期'], format=fmt, errors='coerce')
            if not df['上市日期'].isna().all():
                print(f"使用格式 {fmt} 成功解析日期")
                break
        except:
            continue

    # 如果上述格式都不行，使用自动推断
    if df['上市日期'].isna().all():
        df['上市日期'] = pd.to_datetime(df['上市日期'], errors='coerce')

    # 提取年、月、日
    df['上市年份'] = df['上市日期'].dt.year
    df['上市月份'] = df['上市日期'].dt.month
    df['上市日'] = df['上市日期'].dt.day

    print("上市日期处理完成")
    return df


def normalize_numeric_data(df):
    """对数值型变量进行归一化处理"""
    print("\n进行数据归一化处理...")

    numeric_columns = ['累计股息（%）', '年均股息（%）', '分红次数', '融资总额（亿元）']
    normalized_data = pd.DataFrame()

    for col in numeric_columns:
        if col in df.columns:
            # 清理数据：移除可能的特殊字符并转换为数值
            df[col] = pd.to_numeric(df[col].astype(str).str.replace('[^0-9.-]', '', regex=True), errors='coerce')

            # 创建归一化列名
            norm_col = f'{col}_归一化'

            # 使用MinMax归一化
            scaler = MinMaxScaler()
            normalized_values = scaler.fit_transform(df[[col]])
            normalized_data[norm_col] = normalized_values.flatten()

            print(f"变量 '{col}' 归一化完成")
        else:
            print(f"警告: 列 '{col}' 不存在")

    # 横向合并归一化数据
    if not normalized_data.empty:
        df_normalized = pd.concat([df, normalized_data], axis=1)
        print("数据归一化处理完成")
        return df_normalized
    else:
        print("没有可归一化的数值型数据")
        return df


def data_preprocessing():
    """主预处理函数"""
    input_file = "新浪财经历史分红数据.xlsx"
    output_file = "新浪财经历史分红数据_预处理.xlsx"

    # 检查输入文件是否存在
    if not os.path.exists(input_file):
        print(f"错误: 输入文件 '{input_file}' 不存在")
        print("请先运行 data_crawler.py 爬取数据")
        return None

    try:
        # 读取数据
        print("读取数据文件...")
        df = pd.read_excel(input_file)

        # 任务2：输出数据形状
        check_data_shape(df)

        # 任务2：重复值检查
        check_duplicates(df)

        # 任务3：展示前5行数据
        first_5_rows = display_first_rows(df)

        # 观察数据问题并调整
        print("\n数据问题观察与调整:")

        # 检查缺失值
        print("缺失值统计:")
        print(df.isnull().sum())

        # 处理缺失值（根据实际情况调整）
        # 这里简单用前向填充处理
        df_cleaned = df.fillna(method='ffill')

        # 任务4：处理上市日期
        df_processed = process_listing_date(df_cleaned)

        # 任务5：数值型变量归一化
        df_final = normalize_numeric_data(df_processed)

        # 任务6：保存预处理后的数据
        df_final.to_excel(output_file, index=False)
        print(f"\n预处理完成！数据已保存到: {output_file}")

        # 显示预处理后的数据信息
        print("\n预处理后的数据信息:")
        print(f"最终数据形状: {df_final.shape}")
        print(f"列名: {list(df_final.columns)}")

        return df_final

    except Exception as e:
        print(f"预处理过程中发生错误: {e}")
        return None


if __name__ == "__main__":
    data_preprocessing()